/**
 * 打开一个串口, 调用起浏览器UI
 * @param baudRate
 * @param dataBits
 * @param parity
 * @param stopBits
 * @param bufferSize
 * @returns {Promise<SerialPort>}
 */
export async function openSerial({baudRate, dataBits, parity, stopBits, bufferSize}) {
    console.log({baudRate, dataBits, parity, stopBits, bufferSize})
    const port = await navigator.serial.requestPort()
    await port.open({baudRate, dataBits, parity, stopBits, bufferSize})
    return port
}


/**
 * 读取串口数据并转化成指定格式
 * @param port 串口对象
 * @param keepReading 流控制方式
 * @param readCallback 处理数据的回调函数
 * @param readSize 读取块大小
 * @returns {Promise<void>}
 */
export async function readFromPort(port, keepReading, readCallback, readSize = 64) {
    while (port && port.readable && keepReading) {
        try {
            // 获取串口的可读流，并为其创建读取器
            const reader = port.readable.getReader();
            let buffer = new Uint8Array(0);  // 使用 Uint8Array 来存储接收到的二进制数据

            while (true) {
                const {value, done} = await reader.read();
                if (done) {
                    break;
                }

                // 将接收到的数据拼接到缓冲区
                const newBuffer = new Uint8Array(buffer.length + value.length);
                newBuffer.set(buffer);
                newBuffer.set(value, buffer.length);
                buffer = newBuffer;

                // 当缓冲区的数据长度超过或等于指定大小时
                while (buffer.length >= readSize) {
                    // 获取指定大小的数据
                    const chunk = buffer.slice(0, readSize);
                    buffer = buffer.slice(readSize);  // 更新缓冲区，保留剩余数据

                    // 将数据转换为十六进制字符串并输出
                    console.log(toHex(chunk));

                    // 调用回调函数，传入处理后的数据
                    readCallback(chunk);
                }
            }
        } catch (err) {
            console.error('Error reading from port:', err);
        }
    }
}

// 将 Uint8Array 转换为十六进制字符串
function toHex(uint8Array) {
    return Array.from(uint8Array).map(byte => byte.toString(16).padStart(2, '0')).join('').toUpperCase();
}

/**
 * 读取固定字节数(serial)
 * @param reader 读取流
 * @param buffer 一个固定大小的缓冲区 -> ArrayBuffer(size)
 * @returns {Promise<Uint8Array>}
 */
export async function readInto(reader, buffer) {
    let offset = 0;
    try {
        while (offset < buffer.byteLength) {
            const {value, done} = await reader.read(
                new Uint8Array(buffer, offset)
            );
            if (done) {
                console.log("done.... 释放读取锁")
                // 释放读取流
                reader.releaseLock();
                break
            }
            // 更新缓冲区
            buffer = value.buffer;
            offset += value.byteLength;

            // 如果偏移量超过缓冲区大小，跳过当前帧
            if (offset > buffer.byteLength) {
                console.warn("Buffer Overrun Error: Skipping current frame");
                offset = buffer.byteLength;  // Reset offset to buffer size to skip this frame
            }

        }
    } catch (e) {
        console.error(e);
    }
    return buffer;
}

async function readChunkSize(reader, chunkSize) {
    const decoder = new TextDecoder(); // 用于将二进制数据转换为字符串
    let result = '';
    let done = false;

    while (!done) {
        // 每次读取chunkSize字节的数据
        const {value, done: doneReading} = await reader.read();
        done = doneReading;

        if (value) {
            // 通过TextDecoder转换二进制数据为文本
            result += decoder.decode(value, {stream: true});
        }
    }
    console.log(result)

    return result;
}


/**
 * 写入数据到串口
 * @param writer 写入流
 * @param buffer 一个固定大小的缓冲区
 * @returns {Promise<void>}
 * @constructor
 */
export async function sendToPort(writer, buffer) {
    await writer.write(buffer);
    writer.releaseLock();
}

/**
 * 通过提供writable 进行写入
 * @param writable 来自于SerialPort对象的writable属性
 * @param buffer 写入字节内容
 * @returns {Promise<void>}
 */
export async function sendToPortByWritable(writable, buffer) {
    console.log(writable)
    let writer;
    try {
        writer = writable.getWriter({mode: "byob"})
        writer.write(buffer);
    } catch (e) {
        console.error(e)
    } finally {
        writer.releaseLock();
    }
}

export async function readFixedBytes(reader, byteCount) {
    const buffer = new Uint8Array(byteCount); // 创建缓冲区
    let offset = 0;

    try {
        while (offset < byteCount) {
            const {value, done} = await reader.read();
            if (done) {
                reader.releaseLock()
                break
            }

            const chunk = value.subarray(0, Math.min(value.length, byteCount - offset));
            console.log(value)
            buffer.set(chunk, offset); // 填充缓冲区
            offset += chunk.length;
        }
    } catch (e) {
        console.error(e)
    }

    return buffer.slice(0, offset); // 返回已读取的字节
}

export async function readUtil(readable) {

    const reader = readable.getReader()
    try {
        while (true) {
            const {value, done} = await reader.read()
            if (done) {
                break
            }
            console.log(value)
            return value
        }
    } catch (error) {
    } finally {
        reader.releaseLock()
    }

}
